package kongkong;

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import org.json.JSONObject;

import com.baidu.aip.imageprocess.AipImageProcess;

import javafx.application.Platform;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.util.Callback;

@SuppressWarnings("rawtypes")
public class StartAppController {
	private Stage primaryStage;
	//文件处理列表
	@FXML
	protected TableView tableView;
	@FXML
	TableColumn tableFilePath;
	@FXML
	TableColumn tableFileOldSize;
	@FXML
	TableColumn tableFileOldDpi;
	@FXML
	TableColumn tableFileNewSize;
	@FXML
	TableColumn tableFileNewDpi;
	@FXML
	TableColumn tableFileResult;
	//水印
	@FXML
	protected CheckBox watermarkCheckBox;
	//强制使用特定分辨率
	@FXML
	protected CheckBox dpiCheckBox;
	@FXML
	protected TextField widthTextField;
	@FXML
	protected TextField heightTextField;
	//水印路径提示
	@FXML
	protected Label watermarkPathLabel;
	//压缩质量滑动按钮
	@FXML
	protected Slider quality;
	//压缩质量提示
	@FXML
	protected Label qualityLabel;
	//输出地址
	@FXML
	protected Label outputPathLabel;
	//加载弹出框
	private static LoadingDialog loading = null;
	
	private final ObservableList<Map<String, String>> data = FXCollections.observableArrayList();
	private String outputPath = null;
	private final List<File> images = new ArrayList<File>();
	private int qualityNumber = 80;
	private boolean watermark = false;
	private boolean dpi = false;
	private String watermarkPath = null;
	private String choseDirPath = "";
	
	@SuppressWarnings("unchecked")
	public void load(Stage primaryStage) {
		this.primaryStage = primaryStage;
		
		quality.setValue(qualityNumber*1.0);
		quality.setMax(100d);
		qualityLabel.setText(qualityNumber+"%");
		outputPathLabel.setText("未选择输出路径");
		widthTextField.setText("1280");
		heightTextField.setText("960");
		
		loading = new LoadingDialog(primaryStage);
		
		//压缩质量
		quality.valueProperty().addListener(new ChangeListener<Number>() {
            public void changed(ObservableValue<? extends Number> ov,  Number old_val, Number new_val) {
              	qualityNumber = (int)new_val.doubleValue();
               	qualityLabel.setText(String.format("%d", qualityNumber)+"%");
            }
        });
		
		//选择水印
		watermarkCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
            public void changed(ObservableValue<? extends Boolean> ov,  Boolean old_val, Boolean new_val) {
            	watermark = watermarkCheckBox.isSelected();
            	if(watermark) {
            		FileChooser fileChooser = new FileChooser();
            		fileChooser.setTitle("选择水印文件");
            		fileChooser.getExtensionFilters().addAll(
            			    new FileChooser.ExtensionFilter("PNG", "*.png")
            				);
            		File watermark =  fileChooser.showOpenDialog(primaryStage);
            		watermarkPath = watermark.getAbsolutePath();
            		watermarkPathLabel.setText(watermarkPath);
            	}
            }
     	});
		
		dpiCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
            public void changed(ObservableValue<? extends Boolean> ov,  Boolean old_val, Boolean new_val) {
            	dpi = dpiCheckBox.isSelected();
            }
     	});
		
		tableFilePath.setCellValueFactory(new Callback() {
			@Override
			public Object call(Object param) {
				CellDataFeatures temp = (CellDataFeatures)param;
				Map map = (Map)temp.getValue();
				return new ReadOnlyObjectWrapper<String>(map.get("path")+"");
			}
		});
		tableFileOldSize.setCellValueFactory(new Callback() {
			@Override
			public Object call(Object param) {
				CellDataFeatures temp = (CellDataFeatures)param;
				Map map = (Map)temp.getValue();
				return new ReadOnlyObjectWrapper<String>(map.get("oldSize")+"");
			}
		});
		tableFileOldDpi.setCellValueFactory(new Callback() {
			@Override
			public Object call(Object param) {
				CellDataFeatures temp = (CellDataFeatures)param;
				Map map = (Map)temp.getValue();
				return new ReadOnlyObjectWrapper<String>(map.get("oldDpi")+"");
			}
		});
		tableFileNewSize.setCellValueFactory(new Callback() {
			@Override
			public Object call(Object param) {
				CellDataFeatures temp = (CellDataFeatures)param;
				Map map = (Map)temp.getValue();
				return new ReadOnlyObjectWrapper<String>(map.get("newSize")+"");
			}
		});
		tableFileNewDpi.setCellValueFactory(new Callback() {
			@Override
			public Object call(Object param) {
				CellDataFeatures temp = (CellDataFeatures)param;
				Map map = (Map)temp.getValue();
				return new ReadOnlyObjectWrapper<String>(map.get("newDpi")+"");
			}
		});
		tableFileResult.setCellValueFactory(new Callback() {
			@Override
			public Object call(Object param) {
				CellDataFeatures temp = (CellDataFeatures)param;
				Map map = (Map)temp.getValue();
				return new ReadOnlyObjectWrapper<String>(map.get("result")+"");
			}
		});
		
		tableView.setItems(data);
	}
	
	@FXML
	protected void closeBtn()throws Exception{
		Platform.exit();
		System.exit(1);
	}
	
	@FXML
	protected void addFiles()throws Exception{
		FileChooser fileChooser = new FileChooser();
		fileChooser.setTitle("选择文件");
		fileChooser.getExtensionFilters().addAll(
			    new FileChooser.ExtensionFilter("全部图片", "*.*"),
			    new FileChooser.ExtensionFilter("JPEG", "*.jpeg"),
			    new FileChooser.ExtensionFilter("JPG", "*.jpg"),
			    new FileChooser.ExtensionFilter("BMP", "*.bmp"),
			    new FileChooser.ExtensionFilter("PNG", "*.png")
				);
		List<File> list =  fileChooser.showOpenMultipleDialog(primaryStage);
		images.clear();
		if(list == null || list.size()==0){
			choseRenderRow();
			return;
		}
		String []paths = list.get(0).getAbsolutePath().split("\\\\");
		//获取当前文件的绝对路径
		choseDirPath = list.get(0).getAbsolutePath().replace(paths[paths.length-1], "");
		images.addAll(list);
		choseRenderRow();
	}
	
	@FXML
	protected void addDirectory()throws Exception{
		loading.activate();
		DirectoryChooser fileChooser = new DirectoryChooser();
		fileChooser.setTitle("请选择文件夹");
		File file = fileChooser.showDialog(primaryStage);
		images.clear();
		if(file==null) {
			choseRenderRow();
			loading.cancel();
			return;
		}
		choseDirPath = file.getAbsolutePath();
		if(file != null){
			File[] files = file.listFiles();
			for(File f : files){
				findImage(f);
//				System.out.println(f.getAbsolutePath());
			}
		}
		choseRenderRow();
		loading.cancel();
	}
	
	@SuppressWarnings("unchecked")
	private void choseRenderRow() {
		data.clear();
		for(File image : images) {
			if(image==null||!image.exists()) {
				continue;
			}
			Map row = new HashMap<String, String>();
			row.put("path", image.getAbsoluteFile());
			BufferedImage bi = null;
			try {
				bi = ImageIO.read(image);
				if(bi==null) {
					continue;
				}
				row.put("oldDpi", bi.getWidth()+"*"+bi.getHeight());
				byte[] data = ((DataBufferByte)bi.getData().getDataBuffer()).getData();
				row.put("oldSize", data.length/1024+"KB");
			} catch (IOException e) {
			}
			row.put("newSize", "");
			row.put("newDpi", "");
			row.put("result", "");
			data.add(row);
		}
	}
	
	private void findImage(File file) {
		if(file.isDirectory()) {
			File[] files = file.listFiles();
			for(File f : files){
				findImage(f);
			}
		}else {
			if(file.getName().toUpperCase().indexOf("JPG")!=-1
					||file.getName().toUpperCase().indexOf("BMP")!=-1
					||file.getName().toUpperCase().indexOf("PNG")!=-1
					||file.getName().toUpperCase().indexOf("JPEG")!=-1) {
				images.add(file);
			}
		}
	}
	
	@FXML
	protected void choseOutputDirectory()throws Exception{
		DirectoryChooser fileChooser = new DirectoryChooser();
		fileChooser.setTitle("请选择输出文件夹");
		File file = fileChooser.showDialog(primaryStage);
		if(file!=null) {
			outputPath = file.getAbsolutePath();
			outputPathLabel.setText("输出："+ outputPath);
		}else {
			outputPath = null;
			outputPathLabel.setText("未选择输出路径");
		}
	}
	
	@FXML
	protected void clearFiles()throws Exception{
		images.clear();
		data.clear();
	}
	
	@FXML
	protected void start()throws Exception{
		if(outputPath==null||"".equals(outputPath)) {
			alert("缺少输出路径", "请选择输出文件路径");
			return;
		}
		if(images==null||images.size()==0){
			alert("缺少文件", "请选择选择压缩文件");
			return;
		}
		int w = 0;
		if(widthTextField.getText()!=null) {
			try {
				w = Integer.parseInt(widthTextField.getText());
			} catch (Exception e) {
				alert("图片宽度错误", "图片宽度输入错误");
				return;
			}
		}
		int h = 0;
		if(heightTextField.getText()!=null) {
			try {
				h = Integer.parseInt(heightTextField.getText());
			} catch (Exception e) {
				alert("图片高度错误", "图片高度输入错误");
				return;
			}
		}
		loading.activate();
		
		File watermarkFile = null;
		if(watermarkPath!=null) {
			watermarkFile = new File(watermarkPath);
		}
		for(int i=0; i<images.size(); i++) {
			File image = images.get(i);
			if(!image.exists()) {
				renderNewRow(null, i, "未完成");
				continue;
			}
			FileOutputStream fos = null;
			try {
				FileInputStream fis = new FileInputStream(image);
				byte []content = ImageUtil.dealImag(fis, watermarkFile, w, h, qualityNumber/100.0f, 1f, dpi);
				//保留输出时的子文件路径
				String outFilePath = outputPath + image.getAbsolutePath().replace(choseDirPath, "");
				fos = new FileOutputStream(outFilePath);
				fos.write(content);
				
				renderNewRow(outFilePath, i, "完成");
			} catch (Exception e) {
				renderNewRow(null, i, "未完成");
			}finally {
				try {
					if(fos!=null) {
						fos.close();
					}
				} catch (Exception e) {
				}
			}
		}
		loading.cancel();
	}
	
    //设置APPID/AK/SK
    public static final String APP_ID = "你的 App ID";
    public static final String API_KEY = "你的 Api Key";
    public static final String SECRET_KEY = "你的 Secret Key";

	@FXML
	protected void cartoon()throws Exception{
		if(outputPath==null||"".equals(outputPath)) {
			alert("缺少输出路径", "请选择输出文件路径");
			return;
		}
		if(images==null||images.size()==0){
			alert("缺少文件", "请选择选择压缩文件");
			return;
		}
		loading.activate();
		for(int i=0; i<images.size(); i++) {
			File image = images.get(i);
			 // 初始化一个AipImageProcess
	        AipImageProcess client = new AipImageProcess(APP_ID, API_KEY, SECRET_KEY);

	        // 可选：设置网络连接参数
	        client.setConnectionTimeoutInMillis(2000);
	        client.setSocketTimeoutInMillis(60000);

	        // 传入可选参数调用接口
	        HashMap<String, String> options = new HashMap<String, String>();
	        
	        options.put("type", "anime");
	        options.put("mask_id", "3");

	        // 参数为本地路径
	        JSONObject res = client.selfieAnime(image.getAbsolutePath(), options);
			FileOutputStream fos = null;
			try {
				//保留输出时的子文件路径
				String outFilePath = outputPath + File.separatorChar +image.getAbsolutePath().replace(choseDirPath, "");
				fos = new FileOutputStream(outFilePath);
				String base64Image = res.getString("image");
				byte[] imagesBs = Base64.getDecoder().decode(base64Image);
				fos.write(imagesBs);
				
				renderNewRow(outFilePath, i, "漫画完成");
			} catch (Exception e) {
				renderNewRow(null, i, "未完成");
				e.printStackTrace();
			}finally {
				try {
					if(fos!=null) {
						fos.close();
					}
				} catch (Exception e) {
				}
			}
		}
		loading.cancel();
	}
	
	private void renderNewRow(String newFilePath, int index, String msg) {
		for(int i=0; i<data.size(); i ++){
			Map<String, String> row = data.get(i);
			if(index==i) {
				if(newFilePath==null) {
					row.put("result", "未完成");
					continue;
				}
				File newImage = new File(newFilePath);
				if(!newImage.exists()) {
					row.put("result", "未完成");
					continue;
				}
				BufferedImage bi = null;
				try {
					bi = ImageIO.read(newImage);
					row.put("newDpi", bi.getWidth()+"*"+bi.getHeight());
					byte[] data = ((DataBufferByte)bi.getData().getDataBuffer()).getData();
					row.put("newSize", data.length/1024+"KB");
					if(data.length==0){
						row.put("result", "未完成");
					}else {
						row.put("result", "完成");
					}
				} catch (IOException e) {
					row.put("result", "未完成");
				}
			}
		}
		tableView.refresh();
	}
	
	private void alert(String title, String msg) {
		Alert err = new Alert(Alert.AlertType.INFORMATION);
	    Pane pane = new Pane();
	    pane.getChildren().add(new Label(msg));
	    err.setHeaderText(title);
	    err.getDialogPane().setExpandableContent(pane);
	    err.show();
	}
}
